@file:Suppress(
    "unused", "MemberVisibilityCanBePrivate", "RedundantOverride",
    "ConvertSecondaryConstructorToPrimary", "UNUSED_PARAMETER"
)

package com.csw.android.dev_utils.utils

import android.graphics.Canvas
import android.graphics.Rect
import android.view.View
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView

/**
 * RecyclerView间隔线装饰器
 */
open class SpaceLineDecoration : RecyclerView.ItemDecoration {
    companion object {
        fun getInstanceByDp(l: Int, t: Int, r: Int, b: Int, color: Int): SpaceLineDecoration {
            return SpaceLineDecoration(
                ScreenInfo.dp2Px(l.toFloat()),
                ScreenInfo.dp2Px(t.toFloat()),
                ScreenInfo.dp2Px(r.toFloat()),
                ScreenInfo.dp2Px(b.toFloat()),
                color
            )
        }
    }

    private val l: Int
    private val t: Int
    private val r: Int
    private val b: Int
    private val color: Int

    constructor(l: Int, t: Int, r: Int, b: Int, color: Int) : super() {
        this.l = l
        this.t = t
        this.r = r
        this.b = b
        this.color = color
    }

    override fun getItemOffsets(
        outRect: Rect,
        view: View,
        parent: RecyclerView,
        state: RecyclerView.State
    ) {
        super.getItemOffsets(outRect, view, parent, state)
        if (!skipDrawSpaceLine(parent.getChildViewHolder(view).bindingAdapterPosition)) {
            outRect.set(l, t, r, b)
        }
    }

    override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
        super.onDraw(c, parent, state)
        val childCount = parent.childCount
        var child: View
        val rect = Rect()
        for (i in 0 until childCount) {
            child = parent.getChildAt(i)
            if (skipDrawSpaceLine(parent.getChildViewHolder(child).bindingAdapterPosition)) {
                continue
            }
            rect.set(child.left - l, child.top - t, child.right + r, child.bottom + b)
            if (l > 0) {
                c.save()
                c.clipRect(rect.left, rect.top, rect.left + l, rect.bottom)
                c.drawColor(color)
                c.restore()
            }
            if (t > 0) {
                c.save()
                c.clipRect(rect.left, rect.top, rect.right, rect.top + t)
                c.drawColor(color)
                c.restore()
            }
            if (r > 0) {
                c.save()
                c.clipRect(rect.right - r, rect.top, rect.right, rect.bottom)
                c.drawColor(color)
                c.restore()
            }
            if (b > 0) {
                c.save()
                c.clipRect(rect.left, rect.bottom - b, rect.right, rect.bottom)
                c.drawColor(color)
                c.restore()
            }
        }

    }

    /**
     * 本方法用于跳过间隔线绘制
     * @param adapterPosition item于适配器中的下标
     * @return true 跳过绘制 else 不跳过
     */
    open fun skipDrawSpaceLine(adapterPosition: Int): Boolean {
        return false
    }
}

/**
 * 线性与网格的条目外边距装饰器
 */
abstract class TableMarginDecoration: RecyclerView.ItemDecoration() {

    enum class Direction {
        LEFT,
        TOP,
        RIGHT,
        BOTTOM
    }

    override fun getItemOffsets(
        outRect: Rect,
        view: View,
        parent: RecyclerView,
        state: RecyclerView.State
    ) {
        parent.getChildAdapterPosition(view).let {
            //默认按照垂直方向计算表格
            //先假设为线性布局，计算行列
            val lm = parent.layoutManager
            var column = 0
            var row = it
            var columnCount = 1
            var rowCount = (parent.adapter?.itemCount ?: 1)
            //如果是网格布局，则参照列数进行网格化
            if (lm is GridLayoutManager) {
                columnCount = lm.spanCount
                rowCount = (rowCount + columnCount - 1) / columnCount
                column = it % columnCount
                row = it / columnCount
            }
            //我们最终的目的是外部可以通过元素显示的行列设置外边距，所以这里要参考布局方向进行行列调整。
            if (lm is LinearLayoutManager) {
                if (lm.orientation == LinearLayoutManager.HORIZONTAL) {
                    val tempPosition = column
                    column = row
                    row = tempPosition
                    val tempCount = columnCount
                    columnCount = rowCount
                    rowCount = tempCount
                }
            }
            //对元素进行左上右下的外边距设置
            getItemOffset(
                view,
                parent,
                state,
                column,
                columnCount,
                row,
                rowCount,
                Direction.LEFT
            ).run {
                outRect.left = this
            }
            getItemOffset(
                view,
                parent,
                state,
                column,
                columnCount,
                row,
                rowCount,
                Direction.TOP
            ).run {
                outRect.top = this
            }
            getItemOffset(
                view,
                parent,
                state,
                column,
                columnCount,
                row,
                rowCount,
                Direction.RIGHT
            ).run {
                outRect.right = this
            }
            getItemOffset(
                view,
                parent,
                state,
                column,
                columnCount,
                row,
                rowCount,
                Direction.BOTTOM
            ).run {
                outRect.bottom = this
            }
        }
    }

    /**
     * 获取item的外部边距
     *
     * @param view 当前item视图
     * @param parent 当前RecyclerView
     * @param state 当前RecyclerView状态
     * @param column item所处列
     * @param columnCount 总列数
     * @param row item所处行
     * @param rowCount 总行数
     * @param direction 哪个方向的边距
     */
    abstract fun getItemOffset(
        view: View,
        parent: RecyclerView,
        state: RecyclerView.State,
        column: Int,
        columnCount: Int,
        row: Int,
        rowCount: Int,
        direction: Direction,
    ): Int


}